package ControllerLag;

import DBLag.DbEmployee;
import DBLag.DbShift;
import DBLag.DbWorkingPlan;
import DBLag.IFDbEmployee;
import DBLag.IFDbShift;
import DBLag.IFDbWorkingPlan;
import ModelLag.Employee;
import ModelLag.Shift;
import ModelLag.WorkingPlan;
import java.util.ArrayList;
import java.util.GregorianCalendar;

/**
 * Controllerklasse for WorkingPlan/Shift. Her i foregår en del af sammenkoblingen
 * imellem Workingplans og Shifts.
 * @author DM75 Gruppe 3
 * @version 2011-12-22
 */
public class WorkingPlanCTR {
    private IFDbShift dbShift;
    private IFDbWorkingPlan dbWorkingPlan;
    private IFDbEmployee dbEmployee;
    
    public WorkingPlanCTR()
    {
        dbShift = new DbShift();
        dbWorkingPlan = new DbWorkingPlan();
        dbEmployee = new DbEmployee();
    }
    
    /**
     * Henter alle WorkingPlans som findes.
     * @param retriveAssociation true = assocering til Shift.
     * @return ArrayList med WorkingPlans.
     */
    public ArrayList<WorkingPlan> getAllWorkingPlans(boolean retriveAssociation)
    {
        return dbWorkingPlan.getAllWorkingPlans(retriveAssociation);
    }
    
    
    /**
     * Henter alle WorkingPlans som findes for den angivne måned og lokalitet.
     * @param month Måned 1-12 (Januar-December)
     * @param lokalitet - afdeling i virsomheden.
     * @param retriveAssociation true = associering til Shifts.
     * @return ArrayList med WorkingPlan objekter.
     */
    public ArrayList<WorkingPlan> getWorkingPlansMonthLoc(int month, int year, String location, boolean retriveAssociation)
    {
        return dbWorkingPlan.getWorkingPlansMonthLoc(month, year, location, retriveAssociation);
    }
    
    
    /**
     * 
     * @param date Dato hvor der skal forsøges at oprette en WorkingPlan
     * @param location Afdeling for WorkingPlan
     * @return rc = -1, WorkingPlan findes i forvejen så en ny er ikke oprettet. 
     * rc = 1 ny WorkingPlan oprettet.
     */
    private int createWorkingPlan(GregorianCalendar date, String location)
    {
        int rc = -1;
        if(dbWorkingPlan.getWorkingPlanID(date, location) == -1)
        {
            ArrayList<Shift> shifts = new ArrayList<Shift>();
            WorkingPlan workingPlanObj = new WorkingPlan(date, location, shifts);
            rc = dbWorkingPlan.insertWorkingPlan(workingPlanObj);
        }
        return rc;
    }
    
    public double getHoursFromStartToEnd(String startTime, String endTime)
    {
        int shiftStartMin = (Integer.parseInt(startTime.substring(0,2)))*60 + Integer.parseInt(startTime.substring(3,5));
        int shiftEndMin = (Integer.parseInt(endTime.substring(0,2)))*60 + Integer.parseInt(endTime.substring(3,5));
        double hours = ((double)(shiftEndMin-shiftStartMin)/60);
        return hours;
    }
    
    /**
     * Oprettelse af en Shift hvor der først kaldes til createWorkingPlan() hvor
     * der besluttes om der skal oprettes en ny WorkingPlan eller om der findes en
     * i forvejen for den angivne dato og lokation. Shift tilføjes og kan nu ses på
     * den specifikke WorkingPlan.
     * @param date Dato hvor Shift skal oprettes.
     * @param location Afdeling i virksomheden.
     * @param cprNo CprNummer på Employee.
     * @param startTime Shift starttid (HH:MM).
     * @param endTime Shift sluttid (HH:MM).
     * @return -1 = mislykkedes. 1 = lykkedes.
     */
    public int createShift(GregorianCalendar date, String location, String cprNo, String startTime, String endTime)
    {
        createWorkingPlan(date, location);
        double hours = getHoursFromStartToEnd(startTime, endTime);
        Employee employeeObj = new Employee();
        employeeObj.setCprNo(cprNo);
        Shift shiftObj = new Shift(employeeObj, startTime, endTime, hours, null);
        return dbShift.insertShift(shiftObj, date, location);
    }
    
    /**
     * Sletning af en Shift. Sletter WorkingPlan som har assocering til den Shift der slettes
     * hvis der ikke er andre associceringer til andre Shift objekter.
     * @param date Dato hvor den pågældende Shift findes.
     * @param location Afdeling i virksomheden hvor Shift findes.
     * @param cprNo Employees cprNo for den Shift.
     * @param startTime Starttidspunkt for Shift.
     * @param endTime Sluttidspunkt for Shift.
     * @return -1 = mislykkedes. 1 = lykkedes.
     */
    public int deleteShift(GregorianCalendar date, String location, String cprNo, String startTime, String endTime)
    {
        int rc = dbShift.deleteShift(cprNo, startTime, endTime, date, location);
        //Sletter WorkingPlan hvis der ikke er nogle Shifts tilknyttet.
        WorkingPlan workingPObj = findWorkingPlan(date, location, true);
        if(workingPObj.getShifts().isEmpty())
        {
            deleteWorkingPlan(date, location);
        }
        return rc;
    }
      
    /**
     * Opdatering af en Shift.
     * @param date Dato hvor Shift findes.
     * @param location Afdeling i virkomheden hvor Shift findes.
     * @param cprNo Employee cprNo for den Shift.
     * @param startTime Starttidspunkt for Shift.
     * @param endTime Sluttidspunkt for Shift.
     * @param newCprNo Angives hvis en anden Employee tager denne vagt. Ellers skal der stå det gamle CprNo. (DDMMYY-XXXX)
     * @param newStartTime Angives hvis man vil ændre dette. (HH:MM)
     * @param newEndTime Angives hvis man vil ændre dette. (HH:MM)
     * @return -1 = mislykkedes. 1 = lykkedes.
     */
    public int updateShift(GregorianCalendar date, String location, String cprNo, String startTime, String endTime, String newCprNo, String newStartTime, String newEndTime)
    {
        int shiftStartMin = (Integer.parseInt(newStartTime.substring(0,2)))*60 + Integer.parseInt(newStartTime.substring(3,5));
        int shiftEndMin = (Integer.parseInt(newEndTime.substring(0,2)))*60 + Integer.parseInt(newEndTime.substring(3,5));
        double newHours = ((double)(shiftEndMin-shiftStartMin)/60);
        Shift shiftObj = dbShift.findShift(cprNo, startTime, endTime, date, location, true);
        return dbShift.updateShift(shiftObj, date, location, newCprNo, newStartTime, newEndTime, newHours);
    }
    
    /**
     * Finder de Employees som ikke er optaget af en Shift den valgte dag og derfor godt kan arbejde i det angivne tidsrum.
     * @param date Dato for den nye Shift.
     * @param newShiftStart Starttid for den nye Shift. (HH:MM)
     * @param newShiftEnd Sluttid for den nye Shift. (HH:MM)
     * @return ArrayList med ledige Employees på den angivne dato i det angivne tidsrum.
     */
    public ArrayList<Employee> getEmployeesAvailableForThisShift(GregorianCalendar date, String newShiftStart, String newShiftEnd)
    {
        ArrayList<String> employeeCprNoWorks = dbWorkingPlan.EmployeesWhoAlreadyWorkInThisPeriod(date, newShiftStart, newShiftEnd);
        ArrayList<Employee> allEmployees = dbEmployee.getAllEmployees();
        
        for(String cprNo : employeeCprNoWorks)
        {
            boolean found = false;
            int index = 0;
            while(index < allEmployees.size() && !found)
            {
                if(allEmployees.get(index).getCprNo().equals(cprNo))
                {
                    found = true;
                    allEmployees.remove(index);
                }
                else
                {
                    index++;
                }   
            }
        }
        return allEmployees;
    }
    
    /**
     * Find en WorkingPlan ud fra dato, lokation og om der skal være associeringer til Shifts.
     * @param date Datoen for den WorkingPlan man vil finde.
     * @param location Afdeling i virksomheden som man ønsker at finde WorkingPlan for.
     * @param retriveAssociation true = Associeringer til Shifts laves.
     * @return WorkingPlan objekt.
     */
    public WorkingPlan findWorkingPlan(GregorianCalendar date, String location, boolean retriveAssociation)
    {
        return dbWorkingPlan.findWorkingPlan(date, location, retriveAssociation);
    }
    
    /**
     * Slet en WorkingPlan. Kan kun lade sig at gøre hvis der ikke er nogle reference fra Shifts.
     * Hvis man skal kunne slette en WorkingPlan med referencer så skal der laves Cascade i Databasen.
     * @param date Dato for den WorkingPlan der skal slettes.
     * @param location Afdeling i virksomheden for den WorkingPlan der skal slettes.
     * @return -1 = mislykkedes. 1 = lykkedes.
     */
    public int deleteWorkingPlan(GregorianCalendar date, String location)
    {
        return dbWorkingPlan.deleteWorkingPlan(date, location);
    }  
    
    /**
     * Find en Shift.
     * @param cprNo
     * @param startTime
     * @param endTime
     * @param date
     * @param location
     * @param retriveAssociation
     * @return Shift objekt eller null hvis ikke fundet.
     */
    public Shift findShift(String cprNo, String startTime, String endTime, GregorianCalendar date, String location, boolean retriveAssociation)
    {
        return dbShift.findShift(cprNo, startTime, endTime, date, location, retriveAssociation);
    }
            
}
